//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package external_events_api_serv

import (
	"context"
	"strings"
	"time"

	"atomgit.com/openlinksaas/api-server/bg_runner/tasks"
	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/event_dao"
	"atomgit.com/openlinksaas/api-server/dao/user_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/external_events_api"
	"github.com/dchest/uniuri"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

type ExternalEventsApiImpl struct {
	external_events_api.UnimplementedExternalEventsApiServer
	baseUrl string
}

func NewExternalEventsApiImpl(baseUrl string) *ExternalEventsApiImpl {
	if !strings.HasSuffix(baseUrl, "/") {
		baseUrl = baseUrl + "/"
	}
	baseUrl = baseUrl + "webhook/"
	return &ExternalEventsApiImpl{
		baseUrl: baseUrl,
	}
}

func (apiImpl *ExternalEventsApiImpl) GenIdAndSecret(ctx context.Context, req *external_events_api.GenIdAndSecretRequest) (*external_events_api.GenIdAndSecretResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &external_events_api.GenIdAndSecretResponse{
			Code:   external_events_api.GenIdAndSecretResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &external_events_api.GenIdAndSecretResponse{
			Code:   external_events_api.GenIdAndSecretResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &external_events_api.GenIdAndSecretResponse{
			Code:   external_events_api.GenIdAndSecretResponse_CODE_NO_PROJECT, //FIXME
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	eventSourceId := uuid.NewString()
	return &external_events_api.GenIdAndSecretResponse{
		Code:           external_events_api.GenIdAndSecretResponse_CODE_OK,
		EventSourceId:  eventSourceId,
		Secret:         uniuri.NewLenChars(20, []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")),
		EventSourceUrl: apiImpl.baseUrl + req.ProjectId + "/" + eventSourceId,
	}, nil
}

func (apiImpl *ExternalEventsApiImpl) Create(ctx context.Context, req *external_events_api.CreateRequest) (*external_events_api.CreateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &external_events_api.CreateResponse{
			Code:   external_events_api.CreateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &external_events_api.CreateResponse{
			Code:   external_events_api.CreateResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &external_events_api.CreateResponse{
			Code:   external_events_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &external_events_api.CreateResponse{
			Code:   external_events_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if len(req.EventSourceId) < 16 {
		return &external_events_api.CreateResponse{
			Code:   external_events_api.CreateResponse_CODE_WRONG_SECRET,
			ErrMsg: "无效事件源ID",
		}, nil
	}
	if len(req.Secret) < 16 {
		return &external_events_api.CreateResponse{
			Code:   external_events_api.CreateResponse_CODE_WRONG_SECRET,
			ErrMsg: "无效密钥",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6
	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)
	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err := event_dao.EventSourceDao.Insert(sessCtx, &event_dao.EventSourceInfoDbItem{
			EventSourceId: req.EventSourceId,
			EventSource:   int32(req.EventSource),
			Title:         req.Title,
			ProjectId:     req.ProjectId,
			CreateTime:    nowTime,
			UpdateTime:    nowTime,
			CreateUserId:  sessionItem.UserId,
			Secret:        req.Secret,
		})
		if err != nil {
			return &external_events_api.CreateResponse{
				Code:   external_events_api.CreateResponse_CODE_EVENT_SOURCE_EXIST,
				ErrMsg: "事件源已存在",
			}, nil
		}
		err = event_dao.EventSourceStateDao.Insert(sessCtx, &event_dao.EventSourceStateInfoDbItem{
			EventSourceId:  req.EventSourceId,
			UserCountDirty: true,
		})
		if err != nil {
			return nil, err
		}
		go apiImpl.addCreateEvent(sessionItem, req, projectItem, req.EventSourceId, nowTime)
		return &external_events_api.CreateResponse{
			Code: external_events_api.CreateResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*external_events_api.CreateResponse), nil
}

func (apiImpl *ExternalEventsApiImpl) Update(ctx context.Context, req *external_events_api.UpdateRequest) (*external_events_api.UpdateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &external_events_api.UpdateResponse{
			Code:   external_events_api.UpdateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &external_events_api.UpdateResponse{
			Code:   external_events_api.UpdateResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &external_events_api.UpdateResponse{
			Code:   external_events_api.UpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &external_events_api.UpdateResponse{
			Code:   external_events_api.UpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	eventSourceItem, err := event_dao.EventSourceDao.Get(ctx, req.ProjectId, req.EventSourceId)
	if err != nil {
		return &external_events_api.UpdateResponse{
			Code:   external_events_api.UpdateResponse_CODE_NO_EVENT_SOURCE,
			ErrMsg: "事件源不存在",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || eventSourceItem.CreateUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &external_events_api.UpdateResponse{
			Code:   external_events_api.UpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)
	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err := event_dao.EventSourceDao.Update(sessCtx, req.ProjectId, req.EventSourceId, req.Title)
		if err != nil {
			return nil, err
		}
		go apiImpl.addUpdateEvent(sessionItem, req, projectItem, eventSourceItem)
		return &external_events_api.UpdateResponse{
			Code: external_events_api.UpdateResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*external_events_api.UpdateResponse), nil
}

func (apiImpl *ExternalEventsApiImpl) List(ctx context.Context, req *external_events_api.ListRequest) (*external_events_api.ListResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &external_events_api.ListResponse{
			Code:   external_events_api.ListResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &external_events_api.ListResponse{
			Code:   external_events_api.ListResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &external_events_api.ListResponse{
			Code:   external_events_api.ListResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &external_events_api.ListResponse{
			Code:   external_events_api.ListResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	eventSourceItemList, err := event_dao.EventSourceDao.List(ctx, req.ProjectId)
	if err != nil {
		return nil, err
	}
	infoList := []*external_events_api.EventSourceInfo{}
	eventSourceIdList := []string{}
	for _, eventSourceItem := range eventSourceItemList {
		info := eventSourceItem.ToEventSourceInfo(apiImpl.baseUrl)
		info.ProjectName = projectItem.BasicInfo.ProjectName
		info.EventSourceUrl = apiImpl.baseUrl + info.ProjectId + "/" + info.EventSourceId
		infoList = append(infoList, info)
		eventSourceIdList = append(eventSourceIdList, info.EventSourceId)
	}
	//增加事件源状态
	statList, err := event_dao.EventSourceStateDao.ListById(ctx, eventSourceIdList)
	if err != nil {
		return nil, err
	}
	stateMap := map[string]*event_dao.EventSourceStateInfoDbItem{}
	for _, stat := range statList {
		stateMap[stat.EventSourceId] = stat
	}
	for _, info := range infoList {
		stat, ok := stateMap[info.EventSourceId]
		if !ok {
			stat = &event_dao.EventSourceStateInfoDbItem{
				EventSourceId:  info.EventSourceId,
				UserCountDirty: true,
			}
			event_dao.EventSourceStateDao.Insert(ctx, stat) //skip error check
		}
		info.TotalEventCount = stat.EventCount
		if !stat.UserCountDirty {
			info.SourceUserCount = stat.SourceUserCount
			info.MapUserCount = stat.MapUserCount
			continue
		}
		sourceUserCount, mapUserCount, err := apiImpl.getUserCountInfo(ctx, info.ProjectId, info.EventSourceId)
		if err != nil {
			continue
		}
		info.SourceUserCount = sourceUserCount
		info.MapUserCount = mapUserCount
		event_dao.EventSourceStateDao.UpdateUserCount(ctx, info.EventSourceId, sourceUserCount, mapUserCount) //skip error check
	}
	return &external_events_api.ListResponse{
		Code:     external_events_api.ListResponse_CODE_OK,
		InfoList: infoList,
	}, nil
}

func (apiImpl *ExternalEventsApiImpl) Get(ctx context.Context, req *external_events_api.GetRequest) (*external_events_api.GetResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &external_events_api.GetResponse{
			Code:   external_events_api.GetResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Info:   &external_events_api.EventSourceInfo{},
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &external_events_api.GetResponse{
			Code:   external_events_api.GetResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
			Info:   &external_events_api.EventSourceInfo{},
		}, nil
	} else if err == utils.ErrNoRole {
		return &external_events_api.GetResponse{
			Code:   external_events_api.GetResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Info:   &external_events_api.EventSourceInfo{},
		}, nil
	} else if err != nil {
		return nil, err
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &external_events_api.GetResponse{
			Code:   external_events_api.GetResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Info:   &external_events_api.EventSourceInfo{},
		}, nil
	}
	eventSourceItem, err := event_dao.EventSourceDao.Get(ctx, req.ProjectId, req.EventSourceId)
	if err != nil {
		return &external_events_api.GetResponse{
			Code:   external_events_api.GetResponse_CODE_NO_EVENT_SOURCE,
			ErrMsg: "数据源不存在",
			Info:   &external_events_api.EventSourceInfo{},
		}, nil
	}
	info := eventSourceItem.ToEventSourceInfo(apiImpl.baseUrl)
	statItem, err := event_dao.EventSourceStateDao.Get(ctx, req.EventSourceId)
	if err == nil {
		info.TotalEventCount = statItem.EventCount
		if statItem.UserCountDirty {
			sourceUserCount, mapUserCount, err := apiImpl.getUserCountInfo(ctx, info.ProjectId, info.EventSourceId)
			if err == nil {
				info.SourceUserCount = sourceUserCount
				info.MapUserCount = mapUserCount
				event_dao.EventSourceStateDao.UpdateUserCount(ctx, info.EventSourceId, sourceUserCount, mapUserCount) //skip error check
			}
		} else {
			info.SourceUserCount = statItem.SourceUserCount
			info.MapUserCount = statItem.MapUserCount
		}
	}

	return &external_events_api.GetResponse{
		Code: external_events_api.GetResponse_CODE_OK,
		Info: info,
	}, nil
}

func (apiImpl *ExternalEventsApiImpl) getUserCountInfo(ctx context.Context, projectId, eventSourceId string) (uint32, uint32, error) {
	sourceUserCount := uint32(0)
	mapUserCount := uint32(0)
	userItemList, err := event_dao.SourceUserDao.List(ctx, projectId, eventSourceId)
	if err != nil {
		return sourceUserCount, mapUserCount, err
	}
	for _, userItem := range userItemList {
		sourceUserCount += 1
		if userItem.UserPolicy == int32(external_events_api.SOURCE_USER_POLICY_SOURCE_USER_POLICY_MAPPING) {
			mapUserCount += 1
		}
	}
	return sourceUserCount, mapUserCount, nil
}
func (apiImpl *ExternalEventsApiImpl) GetSecret(ctx context.Context, req *external_events_api.GetSecretRequest) (*external_events_api.GetSecretResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &external_events_api.GetSecretResponse{
			Code:   external_events_api.GetSecretResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &external_events_api.GetSecretResponse{
			Code:   external_events_api.GetSecretResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &external_events_api.GetSecretResponse{
			Code:   external_events_api.GetSecretResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	eventSourceItem, err := event_dao.EventSourceDao.Get(ctx, req.ProjectId, req.EventSourceId)
	if err != nil {
		return &external_events_api.GetSecretResponse{
			Code:   external_events_api.GetSecretResponse_CODE_NO_EVENT_SOURCE,
			ErrMsg: "事件源不存在",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || eventSourceItem.CreateUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &external_events_api.GetSecretResponse{
			Code:   external_events_api.GetSecretResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	go apiImpl.addGetSecretEvent(sessionItem, req, projectItem, eventSourceItem)
	return &external_events_api.GetSecretResponse{
		Code:   external_events_api.GetSecretResponse_CODE_OK,
		Secret: eventSourceItem.Secret,
	}, nil
}

func (apiImpl *ExternalEventsApiImpl) Remove(ctx context.Context, req *external_events_api.RemoveRequest) (*external_events_api.RemoveResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &external_events_api.RemoveResponse{
			Code:   external_events_api.RemoveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &external_events_api.RemoveResponse{
			Code:   external_events_api.RemoveResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &external_events_api.RemoveResponse{
			Code:   external_events_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	eventSourceItem, err := event_dao.EventSourceDao.Get(ctx, req.ProjectId, req.EventSourceId)
	if err != nil {
		return &external_events_api.RemoveResponse{
			Code:   external_events_api.RemoveResponse_CODE_NO_EVENT_SOURCE,
			ErrMsg: "事件源不存在",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || eventSourceItem.CreateUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &external_events_api.RemoveResponse{
			Code:   external_events_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)
	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err := event_dao.SourceUserDao.RemoveByEventSource(sessCtx, req.ProjectId, req.EventSourceId)
		if err != nil {
			return nil, err
		}
		err = event_dao.EventSourceDao.Remove(sessCtx, req.ProjectId, req.EventSourceId)
		if err != nil {
			return nil, err
		}
		err = event_dao.EventStageDao.RemoveByEventSource(sessCtx, req.ProjectId, req.EventSourceId)
		if err != nil {
			return nil, err
		}
		go apiImpl.addRemoveEvent(sessionItem, req, projectItem, eventSourceItem)
		return &external_events_api.RemoveResponse{
			Code: external_events_api.RemoveResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*external_events_api.RemoveResponse), nil
}

func (apiImpl *ExternalEventsApiImpl) ListSourceUser(ctx context.Context, req *external_events_api.ListSourceUserRequest) (*external_events_api.ListSourceUserResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &external_events_api.ListSourceUserResponse{
			Code:   external_events_api.ListSourceUserResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &external_events_api.ListSourceUserResponse{
			Code:   external_events_api.ListSourceUserResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &external_events_api.ListSourceUserResponse{
			Code:   external_events_api.ListSourceUserResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &external_events_api.ListSourceUserResponse{
			Code:   external_events_api.ListSourceUserResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	sourceUserItemList, err := event_dao.SourceUserDao.List(ctx, req.ProjectId, req.EventSourceId)
	if err != nil {
		return nil, err
	}
	mapUserIdList := []string{}
	for _, sourceUserItem := range sourceUserItemList {
		if sourceUserItem.UserPolicy == int32(external_events_api.SOURCE_USER_POLICY_SOURCE_USER_POLICY_MAPPING) {
			if sourceUserItem.MapUserId != "" {
				mapUserIdList = append(mapUserIdList, sourceUserItem.MapUserId)
			}
		}
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, mapUserIdList)
	if err != nil {
		return nil, err
	}
	mapDisplayNameMap := map[string]string{}
	for _, userItem := range userItemList {
		mapDisplayNameMap[userItem.UserId] = userItem.BasicInfo.DisplayName
	}
	infoList := []*external_events_api.SourceUserInfo{}
	for _, sourceUserItem := range sourceUserItemList {
		displayName := ""
		if sourceUserItem.MapUserId != "" {
			displayName = mapDisplayNameMap[sourceUserItem.MapUserId]
		}
		info := sourceUserItem.ToSourceUserInfo(displayName)
		infoList = append(infoList, info)
	}
	return &external_events_api.ListSourceUserResponse{
		Code:     external_events_api.ListSourceUserResponse_CODE_OK,
		InfoList: infoList,
	}, nil
}

func (apiImpl *ExternalEventsApiImpl) SetSourceUserPolicy(ctx context.Context, req *external_events_api.SetSourceUserPolicyRequest) (*external_events_api.SetSourceUserPolicyResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &external_events_api.SetSourceUserPolicyResponse{
			Code:   external_events_api.SetSourceUserPolicyResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &external_events_api.SetSourceUserPolicyResponse{
			Code:   external_events_api.SetSourceUserPolicyResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &external_events_api.SetSourceUserPolicyResponse{
			Code:   external_events_api.SetSourceUserPolicyResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	eventSourceItem, err := event_dao.EventSourceDao.Get(ctx, req.ProjectId, req.EventSourceId)
	if err != nil {
		return &external_events_api.SetSourceUserPolicyResponse{
			Code:   external_events_api.SetSourceUserPolicyResponse_CODE_NO_EVENT_SOURCE,
			ErrMsg: "事件源不存在",
		}, nil
	}
	if req.UserPolicy == external_events_api.SOURCE_USER_POLICY_SOURCE_USER_POLICY_MAPPING && req.MapUserId == "" {
		return &external_events_api.SetSourceUserPolicyResponse{
			Code:   external_events_api.SetSourceUserPolicyResponse_CODE_NO_MAP_USER,
			ErrMsg: "映射用户缺失",
		}, nil
	}
	mapUserDisplayName := ""
	if req.MapUserId != "" {
		userItem, err := user_dao.UserInfoDao.Get(ctx, req.MapUserId)
		if err != nil {
			return &external_events_api.SetSourceUserPolicyResponse{
				Code:   external_events_api.SetSourceUserPolicyResponse_CODE_NO_MAP_USER,
				ErrMsg: "映射用户不存在",
			}, nil
		}
		mapUserDisplayName = userItem.BasicInfo.DisplayName
	}
	sourceUserItem, err := event_dao.SourceUserDao.Get(ctx, req.ProjectId, req.EventSourceId, req.SourceUserName)
	if err != nil {
		return &external_events_api.SetSourceUserPolicyResponse{
			Code:   external_events_api.SetSourceUserPolicyResponse_CODE_NO_EVENT_SOURCE_USER,
			ErrMsg: "映射用户不存在",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || eventSourceItem.CreateUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &external_events_api.SetSourceUserPolicyResponse{
			Code:   external_events_api.SetSourceUserPolicyResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err := event_dao.SourceUserDao.SetPolicy(sessCtx, req.ProjectId, req.EventSourceId, req.SourceUserName, int32(req.UserPolicy), req.MapUserId)
		if err != nil {
			return nil, err
		}
		err = event_dao.EventSourceStateDao.SetUserCountDirty(sessCtx, req.EventSourceId)
		if err != nil {
			return nil, err
		}
		go apiImpl.addSetSourceUserPolicyEvent(sessionItem, req, projectItem, eventSourceItem, sourceUserItem, mapUserDisplayName)
		if req.UserPolicy == external_events_api.SOURCE_USER_POLICY_SOURCE_USER_POLICY_MAPPING && req.MapUserId != "" {
			err = dao.BgTaskDao.Insert(sessCtx, uuid.NewString(), nowTime, nowTime, &tasks.SetSourceUserMapping{
				ProjectId:      req.ProjectId,
				EventSourceId:  req.EventSourceId,
				SourceUserName: req.SourceUserName,
				MapUserId:      req.MapUserId,
			})
			if err != nil {
				return nil, err
			}
		}
		return &external_events_api.SetSourceUserPolicyResponse{
			Code: external_events_api.SetSourceUserPolicyResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*external_events_api.SetSourceUserPolicyResponse), nil
}
